import matplotlib.pyplot as plt
import numpy as np

# 方法名称
methods = ["FCN", "DeepLabv3+", "STDC", "UNet", "Swin-T", "TransUNet", "Swin-UNet", "ST-UNet",
           "CascadePSP", "GLNet", "FCtL", "MCS", "GINet", "ISDNet", "(Ours)DE-UNet"]

# mIoU 精度
miou = np.array([69.5, 58.68, 73.15, 71.49, 72.44, 70.54, 68.23, 72.96, 70.22, 71.88,
                 72.96, 77.16, 76.45, 74.28, 77.42])

# 速度（FPS）
fps = np.array([2.81, 2.55, 7.96, 0.89, 0.65, 0.27, 0.33, 0.12, 0.05, 0.07,
                0.06, 0.29, 0.15, 11.22, 10.71])

# 创建散点图
plt.figure(figsize=(8, 6))

# 颜色列表
colors = plt.cm.tab10(np.linspace(0, 1, len(methods)))

# 其他方法的散点
for i, method in enumerate(methods[:-1]):  # 排除 DE-UNet
    plt.scatter(fps[i], miou[i], color=colors[i], s=100, label=method)

# DE-UNet 用五角星标注
plt.scatter(fps[-1], miou[-1], color='red', marker='p', s=150, label="DE-UNet", edgecolors='black')

# 存储所有标签对象
text_labels = []

# 找出 FPS ≤ 3 的点
low_fps_indices = np.where(fps <= 3)[0]
low_fps_miou = miou[low_fps_indices]

# 在 mIoU 范围内均匀分布标签
y_positions = np.linspace(np.min(low_fps_miou), np.max(low_fps_miou), len(low_fps_indices))

# 处理文本标签
for i, method in enumerate(methods):
    if fps[i] <= 3:  # 速度较慢的点，文本放在 FPS=4.5 处
        new_x = 4.5
        new_y = y_positions[np.where(low_fps_indices == i)[0][0]]  # 均匀分布 y 轴
        arrowprops = dict(arrowstyle='-', color='gray', lw=0.8)  # 连接线
    else:  # 速度较快的点，正常偏移
        new_x = fps[i] + 0.5
        new_y = miou[i] + 1
        arrowprops = None  # 无需连接线

    text = plt.annotate(method,
                        xy=(fps[i], miou[i]),
                        xytext=(new_x, new_y),
                        fontsize=9, ha='center',
                        arrowprops=arrowprops)
    text_labels.append(text)

# 设置坐标轴
plt.xlabel("Inference Speed (FPS)")
plt.ylabel("mIoU Accuracy (%)")
plt.title("Speed vs. mIoU Accuracy")

# 添加图例
plt.legend(loc="lower right", fontsize=8, frameon=True)

# 显示网格
plt.grid(True, linestyle="--", alpha=0.5)

# 保存图片到本地（EPS 格式）
plt.savefig("scatter_plot_adjusted.eps", format="eps", dpi=300, bbox_inches='tight')

# 显示图像
plt.show()
